<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
    <meta http-equiv="Pragma" content="no-cache">
    <meta http-equiv="Expires" content="0">
    <title>五子棋游戏-AI对战</title>
    <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: 'Microsoft YaHei', Arial, sans-serif;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh;
            display: flex;
            justify-content: center;
            align-items: center;
            touch-action: manipulation;
            -webkit-touch-callout: none;
            -webkit-user-select: none;
            -khtml-user-select: none;
            -moz-user-select: none;
            -ms-user-select: none;
            user-select: none;
        }

        .game-container {
            background: white;
            border-radius: 20px;
            box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
            padding: 30px;
            max-width: 800px;
            width: 100%;
        }

        .game-header {
            text-align: center;
            margin-bottom: 30px;
        }

        .game-title {
            font-size: 32px;
            color: #333;
            margin-bottom: 10px;
            font-weight: bold;
        }

        .game-status {
            font-size: 18px;
            color: #666;
            margin-bottom: 20px;
        }

        .controls {
            display: flex;
            justify-content: center;
            gap: 15px;
            margin-bottom: 30px;
            flex-wrap: wrap;
        }

        .btn {
            padding: 10px 20px;
            border: none;
            border-radius: 25px;
            font-size: 16px;
            cursor: pointer;
            transition: all 0.3s ease;
            font-weight: bold;
            outline: none;
            box-shadow: none;
        }

        .btn:focus,
        .btn:active {
            outline: none;
            box-shadow: none;
        }

        .btn-primary {
            background: linear-gradient(45deg, #667eea, #764ba2);
            color: white;
        }

        .btn-primary:hover {
            background: linear-gradient(45deg, #5a6fd8, #6a42a0);
        }

        .btn-secondary {
            background: #f8f9fa;
            color: #333;
            border: 2px solid #dee2e6;
        }

        .btn-secondary:hover {
            background: #e9ecef;
        }

        .btn-secondary.active {
            background: linear-gradient(45deg, #28a745, #20c997);
            color: white;
            border-color: #28a745;
        }

        .board-container {
            display: flex;
            justify-content: center;
            margin-bottom: 20px;
        }

        .board {
            position: relative;
            background: #deb887;
            border: 3px solid #8b7355;
            border-radius: 10px;
            padding: 10px;
            contain: layout style;
        }

        .board-grid {
            display: grid;
            grid-template-columns: repeat(15, 30px);
            grid-template-rows: repeat(15, 30px);
            gap: 0;
            background: #deb887;
        }

        .cell {
            width: 30px;
            height: 30px;
            border: 1px solid #8b7355;
            display: flex;
            justify-content: center;
            align-items: center;
            cursor: pointer;
            position: relative;
            transition: background-color 0.2s ease;
            touch-action: manipulation;
            -webkit-tap-highlight-color: transparent;
        }

        .cell:hover,
        .cell:active {
            background-color: rgba(255, 255, 255, 0.3);
        }

        .cell.disabled {
            cursor: not-allowed;
        }

        .piece {
            width: 24px;
            height: 24px;
            border-radius: 50%;
            border: 2px solid #333;
            position: absolute;
            animation: placeStone 0.3s ease-out;
            transition: all 0.3s ease;
        }

        .piece.black {
            background: linear-gradient(45deg, #000, #333);
            box-shadow: inset 2px 2px 4px rgba(255, 255, 255, 0.3), 2px 2px 8px rgba(0, 0, 0, 0.5);
        }

        .piece.white {
            background: linear-gradient(45deg, #fff, #f0f0f0);
            box-shadow: inset -2px -2px 4px rgba(0, 0, 0, 0.2), 2px 2px 8px rgba(0, 0, 0, 0.3);
        }

        .piece.last-move {
            border: 3px solid #32cd32;
            box-shadow: 0 0 12px rgba(50, 205, 50, 0.5), inset 0 0 8px rgba(50, 205, 50, 0.2);
            animation: lastMoveGlow 1s ease-in-out;
        }

        .piece.last-move.black {
            border-color: #32cd32;
        }

        .piece.last-move.white {
            border-color: #32cd32;
        }

        @keyframes placeStone {
            from {
                transform: scale(0);
                opacity: 0;
            }

            to {
                transform: scale(1);
                opacity: 1;
            }
        }

        @keyframes lastMoveGlow {
            0% {
                box-shadow: 0 0 12px rgba(50, 205, 50, 0.5);
            }

            50% {
                box-shadow: 0 0 18px rgba(50, 205, 50, 0.7);
            }

            100% {
                box-shadow: 0 0 12px rgba(50, 205, 50, 0.5);
            }
        }

        .player-piece {
            width: 20px;
            height: 20px;
            border-radius: 50%;
            border: 2px solid #333;
        }

        .player-piece.black {
            background: linear-gradient(45deg, #000, #333);
        }

        .player-piece.white {
            background: linear-gradient(45deg, #fff, #f0f0f0);
        }

        .game-info {
            text-align: center;
            margin-top: 20px;
            min-height: 60px;
            display: flex;
            flex-direction: column;
            justify-content: flex-start;
        }

        .current-player {
            font-size: 18px;
            font-weight: bold;
            margin-bottom: 10px;
        }

        .ai-thinking {
            margin-top: 10px;
            color: #666;
            font-size: 14px;
            min-height: 20px;
            display: flex;
            align-items: center;
            justify-content: center;
        }

        .player-indicator {
            display: inline-flex;
            align-items: center;
            gap: 10px;
        }

        .winner-modal {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.7);
            display: flex;
            justify-content: center;
            align-items: center;
            z-index: 99999;
        }

        .winner-content {
            background: white;
            padding: 40px;
            border-radius: 20px;
            text-align: center;
            box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
            animation: modalShow 0.3s ease-out;
            max-width: 90vw;
            max-height: 80vh;
            overflow-y: auto;
        }

        @keyframes modalShow {
            from {
                transform: scale(0.7);
                opacity: 0;
            }

            to {
                transform: scale(1);
                opacity: 1;
            }
        }

        .winner-text {
            font-size: 28px;
            font-weight: bold;
            margin-bottom: 20px;
            color: #333;
        }

        .game-setup {
            margin: 20px 0;
            padding: 20px;
            background: #f8f9fa;
            border-radius: 15px;
            border: 2px dashed #dee2e6;
        }

        .setup-title {
            font-size: 18px;
            font-weight: bold;
            margin-bottom: 15px;
            color: #333;
        }

        .setup-controls {
            display: flex;
            flex-direction: column;
            gap: 15px;
        }

        .setup-row {
            display: flex;
            flex-wrap: wrap;
            gap: 10px;
            justify-content: center;
            align-items: center;
        }

        .first-hand-row {
            display: flex;
            gap: 10px;
            justify-content: center;
            align-items: center;
        }

        .first-hand-row .btn {
            flex: 1;
            min-width: 100px;
            max-width: 150px;
        }

        .modal-buttons {
            display: flex;
            gap: 10px;
            justify-content: center;
            flex-wrap: wrap;
            margin-top: 15px;
        }

        .difficulty-selector {
            display: flex;
            gap: 10px;
            align-items: center;
        }

        .difficulty-label {
            font-weight: bold;
            color: #333;
        }

        .control-row {
            display: flex;
            justify-content: center;
            align-items: center;
            gap: 10px;
            margin-bottom: 15px;
        }

        .difficulty-buttons {
            display: flex;
            gap: 6px;
        }

        .first-hand-controls {
            display: flex;
            gap: 10px;
            justify-content: center;
        }

        @media (max-width: 768px) {
            .difficulty-selector {
                flex-direction: column;
                gap: 8px;
                width: 100%;
            }

            .difficulty-buttons {
                display: flex;
                gap: 6px;
                justify-content: center;
            }

            .difficulty-buttons .btn {
                flex: 0;
                min-width: 80px;
                padding: 10px 8px;
                font-size: 12px;
            }

            .board-grid {
                grid-template-columns: repeat(15, 25px);
                grid-template-rows: repeat(15, 25px);
            }

            .cell {
                width: 25px;
                height: 25px;
            }

            .piece {
                width: 20px;
                height: 20px;
            }
        }
    </style>
</head>

<body>
    <div id="app">
        <div class="game-container">
            <div class="game-header">
                <h1 class="game-title">🔴⚫ 五子棋对战</h1>
                <div class="game-status">{{ gameStatus }}</div>
            </div>

            <div class="controls">
                <div class="control-row">
                    <div class="difficulty-selector">
                        <span class="difficulty-label">AI难度:</span>
                        <div class="difficulty-buttons">
                            <button class="btn btn-secondary" :class="{ active: difficulty === 'hard' }"
                                @click="setDifficulty('hard')" :disabled="gameStarted">高手</button>
                        </div>
                    </div>
                </div>

                <div class="control-row first-hand-controls">
                    <button class="btn btn-secondary" :class="{ active: playerFirst }" @click="playerFirst = true"
                        :disabled="gameStarted">玩家先手</button>
                    <button class="btn btn-secondary" :class="{ active: !playerFirst }" @click="playerFirst = false"
                        :disabled="gameStarted">AI先手</button>
                </div>

                <div class="control-row">
                    <button class="btn btn-primary" @click="startNewGame">{{ gameStarted ? '重新开始' : '开始游戏' }}</button>
                    <button v-if="gameStarted && !gameOver" class="btn btn-secondary"
                        @click="showAbortGameModal">中止游戏</button>
                    <!--                    <button v-if="gameStarted && !gameOver && gameHistory.length > 0" class="btn btn-secondary" @click="undoMove">悔棋</button>-->
                </div>
            </div>
            <div class="board-container">
                <div class="board">
                    <div class="board-grid">
                        <div v-for="(cell, index) in board.flat()" :key="index" class="cell"
                            :class="{ disabled: !gameStarted || gameOver || isAIThinking }"
                            @click="makeMove(Math.floor(index / 15), index % 15)"
                            @touchstart="handleTouchStart($event, Math.floor(index / 15), index % 15)"
                            @touchend="handleTouchEnd($event, Math.floor(index / 15), index % 15)">
                            <div v-if="cell !== 0" class="piece" :class="[
                                cell === 1 ? 'black' : 'white',
                                isLastMove(Math.floor(index / 15), index % 15) ? 'last-move' : ''
                            ]"></div>
                        </div>
                    </div>
                </div>
            </div>

            <div class="game-info">
                <div class="current-player" v-if="gameStarted && !gameOver">
                    <div class="player-indicator">
                        当前回合:
                        <div class="player-piece" :class="currentPlayer === 1 ? 'black' : 'white'"></div>
                        {{ currentPlayer === 1 ? '黑棋' : '白棋' }}
                        {{ (currentPlayer === 1 && playerFirst) || (currentPlayer === 2 && !playerFirst) ? '(玩家)' :
                        '(AI)' }}
                    </div>
                    <div class="ai-thinking">
                        <span v-if="isAIThinking">AI正在思考中...</span>
                    </div>
                </div>
            </div>
        </div>

        <!-- 中止游戏弹窗 -->
        <div v-if="showAbortModal" class="winner-modal" @click="closeAbortModal">
            <div class="winner-content" @click.stop>
                <div class="winner-text">📋 中止当前游戏</div>

                <div class="game-setup">
                    <div class="setup-title">🎮 重新设置游戏</div>
                    <div class="setup-controls">
                        <div class="setup-row">
                            <span class="difficulty-label">AI难度:</span>
                            <div class="difficulty-buttons">
                                <button class="btn btn-secondary" :class="{ active: abortGameDifficulty === 'hard' }"
                                    @click="abortGameDifficulty = 'hard'">高手</button>
                            </div>
                        </div>

                        <div class="setup-row">
                            <button class="btn btn-secondary" :class="{ active: abortGamePlayerFirst }"
                                @click="abortGamePlayerFirst = true">玩家先手</button>
                            <button class="btn btn-secondary" :class="{ active: !abortGamePlayerFirst }"
                                @click="abortGamePlayerFirst = false">AI先手</button>
                        </div>
                    </div>
                </div>

                <div class="modal-buttons">
                    <button class="btn btn-primary" @click="abortAndStartNewGame">开始新游戏</button>
                    <button class="btn btn-secondary" @click="closeAbortModal">继续当前游戏</button>
                </div>
            </div>
        </div>

        <!-- 胜利弹窗 -->
        <div v-if="winner !== null" class="winner-modal" @click="closeWinnerModal">
            <div class="winner-content" @click.stop>
                <div class="winner-text">🎉 {{ getWinnerText() }} 🎉</div>

                <div class="game-setup">
                    <div class="setup-title">🎮 重新设置游戏</div>
                    <div class="setup-controls">
                        <div class="setup-row">
                            <span class="difficulty-label">AI难度:</span>
                            <div class="difficulty-buttons">
                                <button class="btn btn-secondary" :class="{ active: newGameDifficulty === 'hard' }"
                                    @click="newGameDifficulty = 'hard'">高手</button>
                            </div>
                        </div>

                        <div class="setup-row first-hand-row">
                            <button class="btn btn-secondary" :class="{ active: newGamePlayerFirst }"
                                @click="newGamePlayerFirst = true">玩家先手</button>
                            <button class="btn btn-secondary" :class="{ active: !newGamePlayerFirst }"
                                @click="newGamePlayerFirst = false">AI先手</button>
                        </div>
                    </div>
                </div>

                <div class="modal-buttons">
                    <button class="btn btn-primary" @click="startNewGameWithSettings">开始新游戏</button>
                </div>
            </div>
        </div>
    </div>

    <script>
        const { createApp } = Vue;

        createApp({
            data() {
                return {
                    board: Array(15).fill(null).map(() => Array(15).fill(0)),
                    currentPlayer: 1,
                    gameStarted: false,
                    gameOver: false,
                    winner: null,
                    playerFirst: true,
                    difficulty: 'hard',
                    isAIThinking: false,
                    gameHistory: [],
                    lastMovePosition: null, // 记录最后一步的位置
                    touchStartTime: 0,
                    touchStartPos: { x: 0, y: 0 },
                    lastTouchEnd: 0,
                    // 新游戏设置
                    newGameDifficulty: 'hard',
                    newGamePlayerFirst: true,
                    // 中止游戏设置
                    showAbortModal: false,
                    abortGameDifficulty: 'hard',
                    abortGamePlayerFirst: true
                }
            },
            computed: {
                gameStatus() {
                    if (!this.gameStarted) {
                        return '选择游戏设置并开始游戏';
                    }
                    if (this.gameOver) {
                        return '游戏结束';
                    }
                    return '游戏进行中';
                }
            },
            methods: {
                setDifficulty(level) {
                    this.difficulty = level;
                },

                myStart(){
                    this.board = Array(15).fill(null).map(() => Array(15).fill(0));
                    this.currentPlayer = 1;
                    this.gameStarted = true;
                    this.gameOver = false;
                    this.winner = null;
                    this.isAIThinking = false;
                    this.gameHistory = [];
                    this.lastMovePosition = null; // 清除最后一步记录

                    // 如果AI先手，让AI先下
                    if (!this.playerFirst) {
                        this.makeAIMove();
                    }
                },

                startNewGame() {
                    if(this.gameStarted){
                         // 调用后端API获取AI下棋位置
                        const response = fetch('/api/restart', {
                            method: 'POST',
                            headers: {
                                'Content-Type': 'application/json'
                            }
                        }
                        ).then(response => { this.myStart()})
                    }else{
                        this.myStart()
                    }
                },

                startNewGameWithSettings() {
                    this.difficulty = this.newGameDifficulty;
                    this.playerFirst = this.newGamePlayerFirst;
                    this.winner = null;

                    this.startNewGame();

                },

                showAbortGameModal() {
                    this.showAbortModal = true;
                    this.abortGameDifficulty = this.difficulty;
                    this.abortGamePlayerFirst = this.playerFirst;
                },

                closeAbortModal() {
                    this.showAbortModal = false;
                },

                abortAndStartNewGame() {
                    this.difficulty = this.abortGameDifficulty;
                    this.playerFirst = this.abortGamePlayerFirst;
                    this.showAbortModal = false;

                    this.startNewGame();

                },

                closeWinnerModal() {
                    this.winner = null;
                },

                getWinnerText() {
                    if (this.winner === 0) {
                        return '平局';
                    } else if (this.winner === 1) {
                        return this.playerFirst ? '玩家获胜' : 'AI获胜';
                    } else if (this.winner === 2) {
                        return this.playerFirst ? 'AI获胜' : '玩家获胜';
                    }
                    return '游戏结束';
                },

                undoMove() {
                    if (this.gameHistory.length >= 2 && !this.gameOver) {
                        this.gameHistory.pop();
                        this.gameHistory.pop();
                        const lastState = this.gameHistory[this.gameHistory.length - 1];
                        if (lastState) {
                            this.board = lastState.board.map(row => [...row]);
                            this.currentPlayer = lastState.currentPlayer;
                        } else {
                            this.board = Array(15).fill(null).map(() => Array(15).fill(0));
                            this.currentPlayer = 1;
                        }
                        this.gameOver = false;
                        this.winner = null;

                        // 更新最后一步位置
                        this.updateLastMoveFromHistory();

                        // 悔棋后检查是否轮到AI下棋
                        const isAITurn = (this.currentPlayer === 1 && !this.playerFirst) ||
                            (this.currentPlayer === 2 && this.playerFirst);

                        if (isAITurn && !this.gameOver && !this.isAIThinking) {
                            this.makeAIMove();
                        }
                    }
                },

                makeMove(row, col) {
                    // 检查是否可以下子
                    if (!this.gameStarted || this.gameOver || this.board[row][col] !== 0 || this.isAIThinking) {
                        return;
                    }

                    // 检查是否是玩家回合
                    const isPlayerTurn = (this.currentPlayer === 1 && this.playerFirst) ||
                        (this.currentPlayer === 2 && !this.playerFirst);

                    if (!isPlayerTurn) {
                        return;
                    }

                    // 保存游戏状态
                    this.gameHistory.push({
                        board: this.board.map(row => [...row]),
                        currentPlayer: this.currentPlayer
                    });

                    // 下子
                    this.board[row][col] = this.currentPlayer;
                    this.lastMovePosition = { row, col }; // 记录最后一步

                    // 检查是否获胜
                    if (this.checkWinner(row, col)) {
                        this.gameOver = true;
                        this.winner = this.currentPlayer;
                        this.newGameDifficulty = this.difficulty;
                        this.newGamePlayerFirst = this.playerFirst;
                        return;
                    }

                    // 检查是否平局
                    if (this.board.every(row => row.every(cell => cell !== 0))) {
                        this.gameOver = true;
                        this.winner = 0; // 0表示平局
                        this.newGameDifficulty = this.difficulty;
                        this.newGamePlayerFirst = this.playerFirst;
                        return;
                    }

                    // 切换玩家
                    this.currentPlayer = this.currentPlayer === 1 ? 2 : 1;

                    // AI回合
                    const isAITurn = (this.currentPlayer === 1 && !this.playerFirst) ||
                        (this.currentPlayer === 2 && this.playerFirst);

                    if (isAITurn && !this.gameOver) {
                        this.makeAIMove();
                    }
                },

                async makeAIMove() {
                    this.isAIThinking = true;

                    try {
                        // 只发送人类玩家的最新落子位置
                        let lastHumanMove = "";

                        // 查找人类玩家的最后一步
                        if (this.gameHistory.length > 0) {
                            const lastHistory = this.gameHistory[this.gameHistory.length - 1];

                            // 找出这一步下的棋子
                            for (let row = 0; row < 15; row++) {
                                for (let col = 0; col < 15; col++) {
                                    // 确定上一步是谁下的棋子
                                    const wasPlayerTurn = (lastHistory.currentPlayer === 1 && this.playerFirst) ||
                                        (lastHistory.currentPlayer === 2 && !this.playerFirst);

                                    if (lastHistory.board[row][col] === 0 && this.board[row][col] !== 0 && wasPlayerTurn) {
                                        lastHumanMove = String(row) + ',' + String(col);
                                        break;
                                    }
                                }
                                if (lastHumanMove) break;
                            }
                        }

                        // 调用后端API获取AI下棋位置
                        const response = await fetch('/api/move', {
                            method: 'POST',
                            headers: {
                                'Content-Type': 'application/json'
                            },
                            body: JSON.stringify({
                                lastHumanMove: lastHumanMove,
                                aiFirst: !this.playerFirst,
                                currentPlayer: this.currentPlayer
                            })
                        });

                        const result = await response.json();

                        if (result.success) {
                            // 解析AI返回的位置
                            const move = result.move;
                            if (move && move.length >= 2) {
                                const row = move.charCodeAt(0) - 97;
                                const col = move.charCodeAt(1) - 97;
                                console.log(`AI 下棋位置: ${row},${col}`);
                                // 保存游戏状态
                                this.gameHistory.push({
                                    board: this.board.map(row => [...row]),
                                    currentPlayer: this.currentPlayer
                                });

                                this.board[row][col] = this.currentPlayer;
                                this.lastMovePosition = { row: row, col: col };

                                if (this.checkWinner(row, col)) {
                                    this.gameOver = true;
                                    this.winner = this.currentPlayer;
                                    this.newGameDifficulty = this.difficulty;
                                    this.newGamePlayerFirst = this.playerFirst;
                                } else if (this.board.every(row => row.every(cell => cell !== 0))) {
                                    this.gameOver = true;
                                    this.winner = 0;
                                    this.newGameDifficulty = this.difficulty;
                                    this.newGamePlayerFirst = this.playerFirst;
                                } else {
                                    this.currentPlayer = this.currentPlayer === 1 ? 2 : 1;
                                }
                            }
                        } else {
                            console.error('AI move failed:', result.error);
                            // 如果API调用失败，使用随机移动作为后备
                            const randomMove = this.getRandomMove();
                            if (randomMove) {
                                this.gameHistory.push({
                                    board: this.board.map(row => [...row]),
                                    currentPlayer: this.currentPlayer
                                });

                                this.board[randomMove.row][randomMove.col] = this.currentPlayer;
                                this.lastMovePosition = { row: randomMove.row, col: randomMove.col };

                                if (this.checkWinner(randomMove.row, randomMove.col)) {
                                    this.gameOver = true;
                                    this.winner = this.currentPlayer;
                                } else if (this.board.every(row => row.every(cell => cell !== 0))) {
                                    this.gameOver = true;
                                    this.winner = 0;
                                } else {
                                    this.currentPlayer = this.currentPlayer === 1 ? 2 : 1;
                                }
                            }
                        }
                    } catch (error) {
                        console.error('Error calling AI API:', error);
                        // 错误情况下使用随机移动
                        const randomMove = this.getRandomMove();
                        if (randomMove) {
                            this.gameHistory.push({
                                board: this.board.map(row => [...row]),
                                currentPlayer: this.currentPlayer
                            });

                            this.board[randomMove.row][randomMove.col] = this.currentPlayer;
                            this.lastMovePosition = { row: randomMove.row, col: randomMove.col };

                            if (this.checkWinner(randomMove.row, randomMove.col)) {
                                this.gameOver = true;
                                this.winner = this.currentPlayer;
                            } else if (this.board.every(row => row.every(cell => cell !== 0))) {
                                this.gameOver = true;
                                this.winner = 0;
                            } else {
                                this.currentPlayer = this.currentPlayer === 1 ? 2 : 1;
                            }
                        }
                    }

                    this.isAIThinking = false;
                },

                getRandomMove() {
                    const emptyCells = [];
                    for (let i = 0; i < 15; i++) {
                        for (let j = 0; j < 15; j++) {
                            if (this.board[i][j] === 0) {
                                emptyCells.push({ row: i, col: j });
                            }
                        }
                    }
                    if (emptyCells.length > 0) {
                        return emptyCells[Math.floor(Math.random() * emptyCells.length)];
                    }
                    return null;
                },

                countInLine(row, col, dx, dy, player) {
                    let count = 1;

                    // 正方向计数
                    let pos = 1;
                    while (pos < 15) {
                        const newRow = row + pos * dx;
                        const newCol = col + pos * dy;
                        if (newRow < 0 || newRow >= 15 || newCol < 0 || newCol >= 15) break;
                        if (this.board[newRow][newCol] === player) {
                            count++;
                            pos++;
                        } else {
                            break;
                        }
                    }

                    // 负方向计数
                    pos = 1;
                    while (pos < 15) {
                        const newRow = row - pos * dx;
                        const newCol = col - pos * dy;
                        if (newRow < 0 || newRow >= 15 || newCol < 0 || newCol >= 15) break;
                        if (this.board[newRow][newCol] === player) {
                            count++;
                            pos++;
                        } else {
                            break;
                        }
                    }

                    return count;
                },

                checkWinner(row, col) {
                    const player = this.board[row][col];
                    const directions = [[0, 1], [1, 0], [1, 1], [1, -1]];

                    for (const [dx, dy] of directions) {
                        if (this.countInLine(row, col, dx, dy, player) >= 5) {
                            return true;
                        }
                    }

                    return false;
                },

                // 检查是否为最后一步
                isLastMove(row, col) {
                    return this.lastMovePosition &&
                        this.lastMovePosition.row === row &&
                        this.lastMovePosition.col === col;
                },

                // 从历史记录中更新最后一步位置
                updateLastMoveFromHistory() {
                    if (this.gameHistory.length === 0) {
                        this.lastMovePosition = null;
                        return;
                    }

                    // 找到与当前棋盘不同的位置（即最后一步）
                    const currentState = this.gameHistory[this.gameHistory.length - 1];
                    for (let i = 0; i < 15; i++) {
                        for (let j = 0; j < 15; j++) {
                            if (this.board[i][j] !== 0 &&
                                (this.gameHistory.length === 1 ||
                                    (this.gameHistory.length > 1 &&
                                        this.gameHistory[this.gameHistory.length - 2].board[i][j] === 0))) {
                                this.lastMovePosition = { row: i, col: j };
                                return;
                            }
                        }
                    }
                    this.lastMovePosition = null;
                },

                handleTouchStart(event, row, col) {
                    this.touchStartTime = Date.now();
                    const touch = event.touches[0];
                    this.touchStartPos = { x: touch.clientX, y: touch.clientY };
                },

                handleTouchEnd(event, row, col) {
                    const touchEndTime = Date.now();
                    const touchDuration = touchEndTime - this.touchStartTime;

                    if (touchDuration < 500) {
                        const touch = event.changedTouches[0];
                        const touchEndPos = { x: touch.clientX, y: touch.clientY };

                        const distance = Math.sqrt(
                            Math.pow(touchEndPos.x - this.touchStartPos.x, 2) +
                            Math.pow(touchEndPos.y - this.touchStartPos.y, 2)
                        );

                        if (distance < 10) {
                            this.makeMove(row, col);
                        }
                    }
                }
            },
            watch: {
                winner(newVal, oldVal) {
                    console.log('Winner changed from', oldVal, 'to', newVal);
                }
            },
            mounted() {
                document.addEventListener('touchstart', (e) => {
                    if (e.touches.length > 1) e.preventDefault();
                }, { passive: false });

                document.addEventListener('touchend', (e) => {
                    const now = Date.now();
                    if (this.lastTouchEnd && (now - this.lastTouchEnd <= 300)) {
                        e.preventDefault();
                    }
                    this.lastTouchEnd = now;
                }, false);

                document.addEventListener('touchmove', (e) => {
                    if (e.target.closest('.board')) {
                        e.preventDefault();
                    }
                }, { passive: false });
            }
        }).mount('#app');
    </script>
</body>

</html>